<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils 0.6: http://docutils.sourceforge.net/" />
<title>EWA Manual</title>
<meta name="author" content="Jacob Smullyan" />
<meta name="organization" content="WNYC New York Public Radio" />
<meta name="copyright" content="Copyright 2006,2010 WNYC New York Public Radio." />
<style type="text/css">

body {
  margin-top: 5px;
  margin-left: 50px;
  margin-right: 50px;
  width: 750px;
  
  padding: 0;
  border: 0;
  color: #530;

  font: 12pt verdana, "Bitstream Vera Sans", geneva, arial, helvetica, helve, sans-serif; 
}

/* em {
  font-family: Times New Roman, Times, serif;
}*/

#table-of-contents { 
  margin-top: 0px;
 }


a.target {
  color: blue }

a.toc-backref {
  text-decoration: none ;
  color: black }

a:hover {
  /* background-color: #cccccc; */
}

cite {
  font-style: normal;
  font-family: monospace;
  font-weight: bold;
}

dd {
  margin-bottom: 0.5em }

div.abstract {
  margin: 2em 5em }

div.abstract p.topic-title {
  font-weight: bold ;
  text-align: center }

div.attention, div.caution, div.danger, div.error, div.hint,
div.important, div.note, div.tip, div.warning {
  margin-left: 4em ;
  padding: 8px;
  text-align: justify;
  font-size: smaller;
  width: 80%;
  border-top: 1px dashed #d33;
  border-bottom: 1px dashed #d33;


 }

div.attention p.admonition-title, div.caution p.admonition-title,
div.danger p.admonition-title, div.error p.admonition-title,
div.warning p.admonition-title {
  color: red ;
  font-weight: bold ;
  font-family: sans-serif;
  text-align: center }

div.hint p.admonition-title, div.important p.admonition-title,
div.note p.admonition-title, div.tip p.admonition-title {
  font-weight: bold ;
  font-family: sans-serif;
  text-align: center }

div.dedication {
  margin: 2em 5em ;
  text-align: center ;
  font-style: italic }

div.dedication p.topic-title {
  font-weight: bold ;
  font-style: normal }

div.figure {
  margin-left: 2em }

div.footer, div.header {
  font-size: smaller }

div.system-messages {
  margin: 5em }

div.system-messages h1 {
  color: red }

div.system-message {
  border: medium outset ;
  padding: 1em }

div.system-message p.system-message-title {
  color: red ;
  font-weight: bold }

div.topic {
  margin: 2em }

h1, h2, h3, h4, h5, h6 {
  /* font-family: Helvetica, Arial, sans-serif; */
  /* border: thin solid black; */
  /* -moz-border-radius: 4px; */
  padding: 4px;
  /* background-color: lightgrey; */
 }

/* h1 {
  background-color: lightgrey;
  border: medium solid black;
  color: #ffffff;
}

h2 {
  background-color: #666666;
  color: #ffffff;
  border: medium solid black;
}

h3, h4, h5, h6 {
  background-color: #cccccc;
  color: #000000;
}
*/

h1.title {
  text-align: center;
  /* background-color: #444499; */
  color: #000;
  border-bottom: thick solid black;
  /* border: thick solid black; */
  /* -moz-border-radius: 20px; */
 }

h2.subtitle {
  text-align: center }

hr {
  width: 75% }

ol.simple, ul.simple {
  margin-bottom: 1em }

ol.arabic {
  list-style: decimal }

ol.loweralpha {
  list-style: lower-alpha }

ol.upperalpha {
  list-style: upper-alpha }

ol.lowerroman {
  list-style: lower-roman }

ol.upperroman {
  list-style: upper-roman }

p { 
 text-align: justify;
 }

p.caption {
  font-style: italic }

p.credits {
  font-style: italic ;
  font-size: smaller }

p.first {
  margin-top: 0 }

p.label {
  white-space: nowrap }

p.topic-title {
  font-weight: bold }

pre { 
   font-size: smaller;
    }

pre.address {
  margin-bottom: 0 ;
  margin-top: 0 ;
  font-family: serif ;
  font-size: 100% }

pre.line-block {
  font-family: serif ;
  font-size: 100% }

pre.literal-block, pre.doctest-block {
  margin-left: 2em ;
  margin-right: 2em ;
  background-color: #EEE;
  border: thin black solid;
  padding: 5px;
}

span.classifier {
  font-family: sans-serif ;
  font-style: oblique }

span.classifier-delimiter {
  font-family: sans-serif ;
  font-weight: bold }

span.interpreted {
  font-family: sans-serif }

span.option-argument {
  font-style: italic }

span.pre {
  white-space: pre }

span.problematic {
  color: red }

table {
  margin-top: 0.5em ;
  margin-bottom: 0.5em }

table.citation {
  border-left: solid thin gray ;
  padding-left: 0.5ex }

table.docinfo {
  font-size: 80%;
  margin-bottom: 25px;
  padding-bottom: 0;
}

table.footnote {
  border-left: solid thin black ;
  padding-left: 0.5ex }

td, th {
  padding-left: 0.5em ;
  padding-right: 0.5em ;
  vertical-align: top }

td > p:first-child, th > p:first-child {
  margin-top: 0em }

th.docinfo-name, th.field-name {
  font-weight: bold ;
  text-align: left ;
  white-space: nowrap }

h1 tt, h2 tt, h3 tt, h4 tt, h5 tt, h6 tt {
  font-size: 80%; }

tt {
  //background-color: #eeeeee;
  color: #000066 }

ul.auto-toc {
  list-style-type: none;
  font-size: 90%;

}

// Highlighting:

.function {color: #000077; font-weight: bold}
.keyword {color: #004444;}
.comment {color: #770000; font-style: italic}
.normal {color: #000000;}
.string {color: #006600;}
.symbol {color: #000000;}

.htmltag {color: #000077;}
.htmlsymbol {color: #000000;}
.htmlnormal {color: #000000;}
.htmlcomment {color: #770000; font-style: italic}
.htmlstring {color: #006600;}
.htmlattr {color: #000000;}


</style>
</head>
<body>
<div class="document" id="ewa-manual">
<h1 class="title">EWA Manual</h1>
<table class="docinfo" frame="void" rules="none">
<col class="docinfo-name" />
<col class="docinfo-content" />
<tbody valign="top">
<tr><th class="docinfo-name">Author:</th>
<td>Jacob Smullyan</td></tr>
<tr><th class="docinfo-name">Contact:</th>
<td><a class="first last reference external" href="mailto:jsmullyan&#64;gmail.com">jsmullyan&#64;gmail.com</a></td></tr>
<tr><th class="docinfo-name">Organization:</th>
<td>WNYC New York Public Radio</td></tr>
<tr><th class="docinfo-name">Version:</th>
<td>0.62.8</td></tr>
<tr><th class="docinfo-name">Copyright:</th>
<td>Copyright 2006,2010 WNYC New York Public Radio.</td></tr>
</tbody>
</table>
<div class="contents topic" id="contents">
<p class="topic-title first">Contents</p>
<ul class="simple">
<li><a class="reference internal" href="#overview" id="id10">Overview</a><ul>
<li><a class="reference internal" href="#modes-of-operation" id="id11">Modes of Operation</a><ul>
<li><a class="reference internal" href="#batch-mode" id="id12">Batch Mode</a></li>
<li><a class="reference internal" href="#server-mode" id="id13">Server Mode</a></li>
</ul>
</li>
<li><a class="reference internal" href="#limitations" id="id14">Limitations</a><ul>
<li><a class="reference internal" href="#a-note-on-mp3-splicing" id="id15">A Note on Mp3 Splicing</a></li>
</ul>
</li>
</ul>
</li>
<li><a class="reference internal" href="#installation" id="id16">Installation</a><ul>
<li><a class="reference internal" href="#supported-platforms" id="id17">Supported Platforms</a></li>
<li><a class="reference internal" href="#getting-ewa" id="id18">Getting Ewa</a></li>
<li><a class="reference internal" href="#software-installation" id="id19">Software Installation</a></li>
<li><a class="reference internal" href="#the-managed-audio-directory" id="id20">The Managed Audio Directory</a></li>
<li><a class="reference internal" href="#permissions-gotchas" id="id21">Permissions Gotchas</a></li>
</ul>
</li>
<li><a class="reference internal" href="#configuration" id="id22">Configuration</a><ul>
<li><a class="reference internal" href="#the-ewa-conf-file" id="id23">The <tt class="docutils literal">ewa.conf</tt> File</a></li>
<li><a class="reference internal" href="#the-ewa-rule-configuration-file" id="id24">The EWA Rule Configuration File</a><ul>
<li><a class="reference internal" href="#the-ewaconf-configuration-language" id="id25">The Ewaconf Configuration Language</a></li>
</ul>
</li>
<li><a class="reference internal" href="#checking-the-syntax-of-the-configuration-files" id="id26">Checking the Syntax of the Configuration Files</a></li>
<li><a class="reference internal" href="#configuring-the-web-server" id="id27">Configuring the Web Server</a><ul>
<li><a class="reference internal" href="#id5" id="id28">Lighttpd</a></li>
<li><a class="reference internal" href="#apache-with-mod-xsendfile" id="id29">Apache with mod_xsendfile</a></li>
</ul>
</li>
</ul>
</li>
<li><a class="reference internal" href="#using-the-cli-programs" id="id30">Using The CLI Programs</a><ul>
<li><a class="reference internal" href="#ewabatch" id="id31"><tt class="docutils literal">ewabatch</tt></a></li>
<li><a class="reference internal" href="#ewa" id="id32"><tt class="docutils literal">ewa</tt></a></li>
<li><a class="reference internal" href="#ewasplice" id="id33"><tt class="docutils literal">ewasplice</tt></a></li>
</ul>
</li>
<li><a class="reference internal" href="#appendix-i-ewaconf-formal-grammar-specification" id="id34">Appendix I. <tt class="docutils literal">ewaconf</tt> Formal Grammar Specification</a><ul>
<li><a class="reference internal" href="#normative-ebnf" id="id35">Normative EBNF</a></li>
<li><a class="reference internal" href="#lexical-details" id="id36">Lexical Details</a><ul>
<li><a class="reference internal" href="#significant-tokens" id="id37">Significant Tokens</a></li>
<li><a class="reference internal" href="#ignored-tokens" id="id38">Ignored Tokens</a></li>
</ul>
</li>
<li><a class="reference internal" href="#complete-example" id="id39">Complete Example</a></li>
</ul>
</li>
</ul>
</div>
<!-- 1  Overview
  1.1  Modes of Operation
    1.1.1  Batch Mode
    1.1.2  Server Mode
  1.2  Limitations
    1.2.1  A Note on Mp3 Splicing
2  Installation
  2.1  Supported Platforms
  2.2  Getting Ewa
  2.3  Software Installation
  2.4  The Managed Audio Directory
  2.5  Permissions Gotchas
3  Configuration
  3.1  The ``ewa.conf`` File
  3.2  The EWA Rule Configuration File
    3.2.1  The Ewaconf Configuration Language
  3.3  Checking the Syntax of the Configuration Files
  3.4  Configuring the Web Server
    3.4.1  Lighttpd
    3.4.2  Apache with mod_xsendfile
4  Using The CLI Programs
  4.1  ``ewabatch``
  4.2  ``ewa``
  4.3  ``ewasplice``
5  Appendix I. ``ewaconf`` Formal Grammar Specification
  5.1  Normative EBNF
  5.2  Lexical Details
    5.2.1  Significant Tokens
    5.2.2  Ignored Tokens
  5.3  Complete Example -->
<div class="section" id="overview">
<h1><a class="toc-backref" href="#id10">Overview</a></h1>
<p>Ewa (East-West Audio) is an application that manages the production of
spliced mp3 files.  It is meant to solve a common audio production
problem facing producers of audio for the web who would like to add
extra content such as credits and promotional or underwriting messages
to their mp3s and be able to update those messages periodically
without having to remaster all their mp3s from scratch.</p>
<p>Ewa makes a distinction between <em>content files</em> and <em>extra files</em>. The
content files contain the material of main interest; the extra files
are the promotional material.  Ewa assumes that one resultant mp3 is
normally an aggregation of exactly one content file with any number of
extra files. <a class="footnote-reference" href="#id6" id="id1">[1]</a></p>
<p>In order to know what extra files to combine with a particular content
file, ewa consults a <em>rule</em>, which is a function that takes the name
of the requested file and returns an ordered list of files that should
be combined.  The rule ewa consults is usually a special kind of rule
called a <em>rule list</em> that contains a list of sub-rules; the first
sub-rule that matches, i.e., that returns a non-empty list, is the
return value of the parent rule.  Ewa provides a expressive
<a class="reference internal" href="#the-ewaconf-configuration-language">mini-language</a> for specifying such rule lists; with it, rules can
apply only for filenames that match glob or regular expression
patterns, or that match date formats, or combinations of such criteria
with &quot;and&quot;, &quot;or&quot;, and &quot;not&quot; operators.  Also, rules can be made active
only for certain date ranges, so you can add configuration in January
that will only become effective in February.  If the rule system isn't
flexible enough and you have special needs, it is also feasible to
plug in your own, implemented in Python.</p>
<p>Ewa also manages transcoding the extra audio to match the content
files with which it may be spliced. Master files for each piece of
extra audio are placed in a directory managed by ewa, and ewa
transcodes them as needed, leaving the transcoded files in another
managed directory for future runs. The masters may be in mp3, wav, or
aiff format.</p>
<div class="section" id="modes-of-operation">
<h2><a class="toc-backref" href="#id11">Modes of Operation</a></h2>
<p>Ewa can operate either in batch mode, in which case it produces
combined files for the content files specified on the command line, or
in server mode.</p>
<div class="section" id="batch-mode">
<h3><a class="toc-backref" href="#id12">Batch Mode</a></h3>
<p>The batch mode, controlled by the script <a class="reference internal" href="#ewabatch">ewabatch</a>, is convenient if
you can't run your own persistent processes on the web server serving
your audio files; you can use it to produce static files on a
machine under your own control and rsync them up to the web server
however often you need.  Batch mode can operate either on individual
files or recursively on entire directories.</p>
</div>
<div class="section" id="server-mode">
<h3><a class="toc-backref" href="#id13">Server Mode</a></h3>
<p>If you are using <tt class="docutils literal">ewabatch</tt> to generate all your files, there is no
need for any integration with the web server at all; you just need a
cron job to generate the files periodically and perhaps rsync them.
But if you have a large number of files, this can become unwieldy. Not
only must each new file must be processed before going live, but the
costs in time and bandwidth of changing intros for a large number of
mp3s and having to rsync them up to your webserver may be prohibitive
if undertaken frequently.  It is highly inefficient to have to move
thousands of files just because an intro has changed.  The ewa server
gets around this problem.</p>
<p>The server mode, controlled by the script <a class="reference internal" href="#ewa">ewa</a>, is a persistent daemon
running a simple <a class="reference external" href="http://wsgi.org/wsgi">WSGI</a> application, normally connected to a web server
via <a class="reference external" href="http://fastcgi.com/">FCGI</a> or <a class="reference external" href="http://www.mems-exchange.org/software/scgi/">SCGI</a>, which generates the composite files on demand,
caching them on the filesystem and rebuilding them upon request with a
configurable frequency.  The path to the composite file is passed to
the webserver via the <a class="reference external" href="http://blog.lighttpd.net/articles/2006/07/02/x-sendfile">X-Sendfile</a> technique (which originated with
<a class="reference external" href="http://lighttpd.net/">lighttpd</a> and is also supported by <a class="reference external" href="http://httpd.apache.org/">apache</a> with the <a class="reference external" href="http://celebnamer.celebworld.ws/stuff/mod_xsendfile/">mod_xsendfile</a>
module; <a class="reference external" href="http://nginx.net/">nginx</a> also has a <a class="reference external" href="http://blog.kovyrin.net/2006/11/01/nginx-x-accel-redirect-php-rails/">similar feature</a> and <a class="reference external" href="http://www.cherokee-project.com/">cherokee</a> supports it
as well).  The webserver is responsible for returning the actual file
over HTTP, and ewa does not need to do IO; as a result, ewa processes
each request extremely quickly, and files are served at almost the
same speed as static files, with excellent scaleability.</p>
</div>
</div>
<div class="section" id="limitations">
<h2><a class="toc-backref" href="#id14">Limitations</a></h2>
<p>Ewa has a few limitations that the user should be aware of.</p>
<ol class="arabic simple">
<li>Mp3 is the only supported audio format.</li>
<li>Ewa only supports CBR (constant bit rate) encoding.</li>
<li>Ewa's rule system only takes into account the name of the requested
content file and the current time and date in determining the list
of files to splice; in particular, it isn't currently suited to
personalizing mp3 downloads.</li>
<li>Ewa currently does not support the dynamic writing of id3 tags; it
takes whatever id3 tags are on the main content file and transfers
them verbatim to the composite.</li>
<li>Ewa relies on the model of one content file + multiple extra files;
scenarios with multiple content files aren't supported.</li>
</ol>
<p>Some or all of these may be addressed in future revisions, depending
on community interest.</p>
<div class="section" id="a-note-on-mp3-splicing">
<h3><a class="toc-backref" href="#id15">A Note on Mp3 Splicing</a></h3>
<p>You will occasionally read that mp3s cannot be reliably spliced, as
mp3 frames may store information used by later frames in the bit
reservoir.  This is not quite true; the reality is that mp3s cannot be
reliably <em>cut and spliced</em>.  In ewa, all the mp3s are spliced on
preexisting mp3 boundaries; they are not cut (except to drop a bad
frame at the end of a file).  Obviously, the last frame in an mp3 does
not store content in the bit reservoir for subsequent frames.
Therefore, the bit reservoir does not present a problem for ewa.</p>
<p>Ewa attempts to produce spliced files that are without bad frames; to
do so, it looks at the frames preceding frame boundaries and discard
broken ones.  However, ewa also attempts to splice very quickly, and
hence cannot scan entire mp3s to clean them; if the mp3s going into
ewa are broken, the ones coming out will be too.</p>
</div>
</div>
</div>
<div class="section" id="installation">
<h1><a class="toc-backref" href="#id16">Installation</a></h1>
<div class="section" id="supported-platforms">
<h2><a class="toc-backref" href="#id17">Supported Platforms</a></h2>
<p>Ewa has been developed and tested on Linux, but should work fine on
any flavor of BSD, including Mac OS X, and commercial UNIX
implementations.  It hasn't been tested on Windows, but in future
might work there in whole or in part.  Please note that some parts of
this manual presuppose a UNIX platform.</p>
<p>Ewa is written in <a class="reference external" href="http://www.python.org/">Python</a>, and requires Python 2.4 or later. In
addition, the following Python packages need to be installed:</p>
<ul class="simple">
<li><a class="reference external" href="http://cheeseshop.python.org/pypi/setuptools">setuptools</a></li>
<li><a class="reference external" href="http://eyed3.nicfit.net/">eyeD3</a></li>
<li><a class="reference external" href="http://cheeseshop.python.org/pypi/flup">flup</a></li>
</ul>
<p>To run tests you also need:</p>
<ul class="simple">
<li><a class="reference external" href="http://somethingaboutorange.com/mrl/projects/nose/">nose</a></li>
</ul>
<p>Ewa also requires that <a class="reference external" href="http://lame.sourceforge.net/">lame</a> be installed for transcoding.  To run the
ewa server, you need to run an http server that supports <a class="reference external" href="http://blog.lighttpd.net/articles/2006/07/02/x-sendfile">X-Sendfile</a>
or something equivalent: either <a class="reference external" href="http://lighttpd.net/">lighttpd</a>, <a class="reference external" href="http://httpd.apache.org/">apache</a> with
<a class="reference external" href="http://celebnamer.celebworld.ws/stuff/mod_xsendfile/">mod_xsendfile</a>, or possibly <a class="reference external" href="http://nginx.net/">nginx</a> or <a class="reference external" href="http://www.cherokee-project.com/">cherokee</a>.</p>
</div>
<div class="section" id="getting-ewa">
<h2><a class="toc-backref" href="#id18">Getting Ewa</a></h2>
<p>Ewa releases are available in binary and source form from
<a class="reference external" href="http://cheeseshop.python.org/pypi/ewa">http://cheeseshop.python.org/pypi/ewa</a>.</p>
<p>If you want to follow the bleeding edge development version, you can
check out the latest source code from our mercurial repository:</p>
<pre class="literal-block">
hg clone https://eastwestaudio.googlecode.com/hg/ ewa
</pre>
</div>
<div class="section" id="software-installation">
<h2><a class="toc-backref" href="#id19">Software Installation</a></h2>
<p>To install, if you already have <a class="reference external" href="http://cheeseshop.python.org/pypi/setuptools">setuptools</a> installed, you can simply
do:</p>
<pre class="literal-block">
easy_install ewa
</pre>
<p>Or, if you have already installed the source tarball and have unpacked
it, cd into it and type:</p>
<pre class="literal-block">
easy_install .
</pre>
<p>or equivalently:</p>
<pre class="literal-block">
python setup.py install
</pre>
</div>
<div class="section" id="the-managed-audio-directory">
<h2><a class="toc-backref" href="#id20">The Managed Audio Directory</a></h2>
<p>Ewa expects audio to be stored in a directory structure like:</p>
<blockquote>
<dl class="docutils">
<dt>$basedir/main</dt>
<dd>Your content mp3s go here; you manage this directory and can
organize it however you like. Ewa needs read access to it.</dd>
<dt>$basedir/extra/master</dt>
<dd>Your &quot;extra&quot; files -- intros, outros, ads, etc. -- go here;
you manage this directory also.  Ewa needs read access to it
also.</dd>
<dt>$basedir/extra/transcoded</dt>
<dd>Ewa manages this directory and needs write access to it; it
stores transcoded versions of the audio files in <tt class="docutils literal">extra/master</tt>
here.</dd>
<dt>$targetdir</dt>
<dd>Ewa manages this directory and needs write access to it; this
is where it stores the spliced files.</dd>
</dl>
</blockquote>
<p><tt class="docutils literal">basedir</tt> and <tt class="docutils literal">targetdir</tt> are configuration-defined.  You must
specify <tt class="docutils literal">basedir</tt> in <tt class="docutils literal">ewa.conf</tt>; <tt class="docutils literal">targetdir</tt> will default to
<tt class="docutils literal">$basedir/combined</tt> if not otherwise specified.</p>
</div>
<div class="section" id="permissions-gotchas">
<h2><a class="toc-backref" href="#id21">Permissions Gotchas</a></h2>
<p>Some care is necessary to ensure that file permissions will be right
for your deployment, especially if you are running both the ewa server
and ewa batch processes, as a variety of users may then be creating
files in the managed directories.</p>
<p>One approach is to create a user and group that the ewa server will
run as, give ownership of the managed directories to it, and make them
both group-writeable and the group permissions sticky.  On Linux, you
might do this:</p>
<pre class="literal-block">
groupadd ewa
useradd -g ewa -s /bin/false  -d $targetdir -c &quot;ewa user&quot; ewa
chown -R ewa:ewa $targetdir $basedir/extra/transcoded
chmod -R g+ws $targetdir $basedir/extra/transcoded
</pre>
<p>While you are at it, creating directories for ewa's pid file and log
file isn't a bad idea:</p>
<pre class="literal-block">
mkdir -p /var/{run,log}/ewa &amp;&amp; chown ewa /var/{run,log}/ewa
</pre>
<p>In <tt class="docutils literal">ewa.conf</tt> you'll want to set the <tt class="docutils literal">user</tt> and <tt class="docutils literal">group</tt>
variables to match the user and group you created.  If you do this,
<tt class="docutils literal">ewa</tt> and <tt class="docutils literal">ewabatch</tt> will need to be run as root (in the case of
<tt class="docutils literal">ewabatch</tt>, most conveniently through <tt class="docutils literal">sudo</tt>), but will drop
credentials to your user/group before it creates any files.</p>
</div>
</div>
<div class="section" id="configuration">
<h1><a class="toc-backref" href="#id22">Configuration</a></h1>
<p>Ewa has two configuration files: <tt class="docutils literal">ewa.conf</tt>, for adminstrative
options, and a rule configuration file, which is used to determine
the playlists.</p>
<div class="section" id="the-ewa-conf-file">
<h2><a class="toc-backref" href="#id23">The <tt class="docutils literal">ewa.conf</tt> File</a></h2>
<p><tt class="docutils literal">ewa.conf</tt> is written in Python; keys defined there that don't start
with an underscore become attributes of the <tt class="docutils literal">ewa.config.Config</tt>
object.  The following are meaningful keys:</p>
<dl class="docutils">
<dt>basedir</dt>
<dd>The path to to the base audio directory.  Must be supplied, as
there is no default.</dd>
<dt>rulefile</dt>
<dd>The path to the file with ewa rules, either in Python, JSON or
ewaconf.  If the file ends with <tt class="docutils literal">.py</tt>, it is assumed to be in
Python; if with <tt class="docutils literal">.json</tt> or <tt class="docutils literal">.js</tt>, in JSON; otherwise
ewaconf.  This also must be supplied.</dd>
<dt>targetdir</dt>
<dd>The path to the directory where ewa will place generated
composite files.  If not supplied, basedir + <tt class="docutils literal">/combined</tt>
will be used.</dd>
<dt>protocol</dt>
<dd>what server protocol to use: one of <tt class="docutils literal">'fcgi'</tt>, <tt class="docutils literal">'scgi'</tt> or
<tt class="docutils literal">'http'</tt>, defaulting to <tt class="docutils literal">'fcgi'</tt>.  <tt class="docutils literal">'http'</tt> is for
development only and should not be used otherwise.</dd>
<dt>interface</dt>
<dd>an ip address like <tt class="docutils literal">'127.0.0.1'</tt>, which is the default.</dd>
<dt>port</dt>
<dd>default: <tt class="docutils literal">5000</tt>.</dd>
<dt>unixsocket</dt>
<dd>if you want to use a UNIX rather than a TCP/IP socket, put the
path to the socket file here; e.g., <tt class="docutils literal">'/var/run/ewa.socket'</tt>.</dd>
<dt>umask</dt>
<dd>if you are using a UNIX socket, this will determine its
permissions; e.g., <tt class="docutils literal">0600</tt>.</dd>
<dt>logfile</dt>
<dd>path to logfile.  By default there is no logfile and hence no
logging.</dd>
<dt>loglevel</dt>
<dd>how much to log -- should be one of <tt class="docutils literal">'debug'</tt>, <tt class="docutils literal">'info'</tt>,
<tt class="docutils literal">'warn'</tt>,  or <tt class="docutils literal">'critical'</tt>, defaulting to <tt class="docutils literal">'critical'</tt>.</dd>
<dt>logrotate</dt>
<dd><p class="first">if you want to rotate your logfiles, set this to one of the
following:</p>
<ul class="last simple">
<li><tt class="docutils literal">True</tt>.  This will result in a logfile that rotates when
the file reaches 10M in size; up to 10 backups will be kept.</li>
<li>an integer meaning the maximum number of bytes that should
be stored before rollover; up to 10 backups will be kept.</li>
<li>a two-tuple of integers specifying the maximum number of
bytes that should be stored before rollover and the number
of backups to retain: e.g., <tt class="docutils literal">(1e7, 5)</tt>.</li>
<li><tt class="docutils literal">'daily'</tt> (rotates every day at midnight regardless of
size)</li>
<li><tt class="docutils literal">'weekly'</tt> (rotates on Monday at midnight)</li>
<li>a value accepted for the <tt class="docutils literal">when</tt> constructor parameter of
<tt class="docutils literal">logging.handlers.TimedRotatingFileHandler</tt> (see Python's
<a class="reference external" href="http://www.python.org/doc/current/lib/node414.html">logging documentation</a> for details): e.g., <tt class="docutils literal">&quot;D&quot;</tt>.</li>
<li>a <tt class="docutils literal">when</tt> parameter, as above, followed by a colon and
a value accepted for <tt class="docutils literal">TimedRotatingFileHandler</tt>'s
<tt class="docutils literal">interval</tt> parameter (an integer); e.g, <tt class="docutils literal">&quot;D:3&quot;</tt>.</li>
</ul>
</dd>
<dt>daemonize</dt>
<dd>whether the server process should daemonize (default:
<tt class="docutils literal">True</tt>).</dd>
<dt>use_xsendfile</dt>
<dd>whether to send an X-Sendfile or equivalent header from the
server process to the front-end web server (default:
<tt class="docutils literal">True</tt>).</dd>
<dt>sendfile_header</dt>
<dd>what flavor of X-Sendfile-ish header to send.
<tt class="docutils literal"><span class="pre">'X-Sendfile'</span></tt> is the default, but lighttpd in versions
&lt;=`.4.11 requires <tt class="docutils literal"><span class="pre">'X-LIGHTTPD-send-file'</span></tt> instead, and
nginx uses <tt class="docutils literal"><span class="pre">'X-Accel-Redirect'</span></tt> (with slightly different
semantics).</dd>
<dt>stream</dt>
<dd>whether to stream the concatenated file directly rather than
saving to disk.  This is not a production-quality option;
don't use it.</dd>
<dt>refresh_rate</dt>
<dd>how often to refresh combined files, in seconds.  Default is
<tt class="docutils literal">0</tt> (never refresh).</dd>
<dt>pidfile</dt>
<dd>if daemonizing, where to put a pidfile (default: <tt class="docutils literal">None</tt>).</dd>
<dt>content_disposition</dt>
<dd>if you want a <tt class="docutils literal"><span class="pre">Content-Disposition:</span> attachment</tt> header, set
this to <tt class="docutils literal">'attachment'</tt>.  Default is <tt class="docutils literal">None</tt>.</dd>
<dt>user</dt>
<dd>If you run in either server or batch mode as root and want to
drop credentials to another user/group, set this.</dd>
<dt>group</dt>
<dd>Same as for user.</dd>
<dt>engine</dt>
<dd>What splicing engine to use.  You don't want to change this or
even know about it.</dd>
<dt>use_threads</dt>
<dd>Whether to use a pool of threads rather than a pool of forked
processes.  If the platform supports <tt class="docutils literal">fork()</tt>, this will
default to <tt class="docutils literal">False</tt>; otherwise (that is, on Windows) to
<tt class="docutils literal">True</tt>.</dd>
<dt>lame_path</dt>
<dd>The path to the <tt class="docutils literal">lame</tt> executable, for transcoding.  Default
is <tt class="docutils literal">/usr/bin/lame</tt>.</dd>
<dt>min_spare</dt>
<dd>For the <a class="reference external" href="http://fastcgi.com/">FCGI</a> and <a class="reference external" href="http://www.mems-exchange.org/software/scgi/">SCGI</a> backends, the minimum number of
spare threads or processes.  Defaults to 1. <a class="footnote-reference" href="#id7" id="id2">[2]</a></dd>
<dt>max_spare</dt>
<dd>For the <a class="reference external" href="http://fastcgi.com/">FCGI</a> and <a class="reference external" href="http://www.mems-exchange.org/software/scgi/">SCGI</a> backends, the maximum number of
spare threads or processes.  Defaults to 5.</dd>
<dt>max_threads</dt>
<dd>For the <a class="reference external" href="http://fastcgi.com/">FCGI</a> and <a class="reference external" href="http://www.mems-exchange.org/software/scgi/">SCGI</a> threaded backends, the maximum
number of threads.  Default is unlimited.</dd>
<dt>max_children</dt>
<dd>For the <a class="reference external" href="http://fastcgi.com/">FCGI</a> and <a class="reference external" href="http://www.mems-exchange.org/software/scgi/">SCGI</a> preforked backends, the maximum
number of child processes.  Default is 50.</dd>
<dt>max_requests</dt>
<dd>For the <a class="reference external" href="http://fastcgi.com/">FCGI</a> and <a class="reference external" href="http://www.mems-exchange.org/software/scgi/">SCGI</a> preforked backends, the maximum
number of requests a child process handles before it is
killed.  Default is 0 (unlimited).</dd>
</dl>
</div>
<div class="section" id="the-ewa-rule-configuration-file">
<h2><a class="toc-backref" href="#id24">The EWA Rule Configuration File</a></h2>
<p>The rule file can be written either in Python or in a special
configuration mini-language, <a class="reference internal" href="#the-ewaconf-configuration-language">ewaconf</a>. <a class="footnote-reference" href="#id8" id="id3">[3]</a></p>
<p>A rule file in Python format gives you maximum flexibility, at the
cost of requiring you to know Python and understand the ewa API.  The
Python file can contain anything as long as it defines a global with
the name <tt class="docutils literal">rules</tt>, which should be a Python callable that, when
called, returns an iterator that yields symbolic names for the files
that should be combined.  (These names will be interpreted as file
paths relative to the <tt class="docutils literal">extra/master</tt> managed directory, unless
they have the Python attribute <tt class="docutils literal">is_original</tt> set to a true value, in
which case, they will interpreted as file paths relative to the
<tt class="docutils literal">main</tt> managed directory.)  With this hook you can load into ewa
just about any sort of rule system that you might like to devise.</p>
<div class="section" id="the-ewaconf-configuration-language">
<h3><a class="toc-backref" href="#id25">The Ewaconf Configuration Language</a></h3>
<p>Ewa's default rule configuration format is designed to make it easy to
define a list of rules that say, for a given mp3 file, what files ewa
should combine to make an aggregate file, and in what order.  The
rules are consulted in order, and checked to see if they match the
input mp3 file; the first one that matches returns a list of files to
combine, and those are then combined.  <tt class="docutils literal">ewaconf</tt> only supports a
limited number of rule types, but nonetheless the system is quite
powerful.</p>
<p>A rule is normally written in the form:</p>
<pre class="literal-block">
condition [options]:
   pre:  [file1,file2...]
   post: [file1,file2...]
</pre>
<p>where a condition is a glob pattern, a regex pattern, or a date
specification, or combinations of the above with with the logical
operators <tt class="docutils literal">and</tt>, <tt class="docutils literal">or</tt>, and <tt class="docutils literal">not</tt>.  The <tt class="docutils literal">pre</tt> and <tt class="docutils literal">post</tt>
lists indicate what files should go before or after the main content
file in the aggregate file ewa produces.  Condition options are put in
brackets after the condition and separated by commas; they can either
be a single symbol, such as <tt class="docutils literal">F</tt> or <tt class="docutils literal">I</tt>, or a name-value pair,
separated by <tt class="docutils literal">=</tt>.  For example:</p>
<pre class="literal-block">
bigband*.mp3 [I]:
  pre: [bigbandintro.wav]
  post: [bigbandoutro.wav]
regex:schwartz.*:
  pre: []
  post: []
and(09/01/2006 - 11/01/2006 [F,fmt=YYYYMMDD],
    or(lopate/*, bl/*):
  pre: []
  post: [specialoutro.mp3]
</pre>
<p>The regular expression follows Python regular expression rules.   If you want a
regex to ignore case, you can pass the <tt class="docutils literal">I</tt> option.  Two other regex
options are supported: <tt class="docutils literal">U</tt> (unicode) and <tt class="docutils literal">L</tt> (locale).  These
correspond to the same options in the Python <tt class="docutils literal">re</tt> module.  For more
information, see the <a class="reference external" href="http://www.python.org/doc/current/lib/module-re.html">official Python documentation</a>.</p>
<p>Globs support only one option: <tt class="docutils literal">I</tt>.  By default, globs are
case-sensitive, but if this option is passed they will ignore case.
(Globs are implemented with Python's <a class="reference external" href="http://www.python.org/doc/current/lib/module-fnmatch.html">fnmatch</a> module.)</p>
<p>Both globs and regexes can contain arbitary characters if they are
delimited with either single or double quotation marks.  They can also
be written without quotation marks, with some restrictions.  Spaces
are not permitted for either; for regexes, colons and commas must be
escaped with a preceding backslash. Unquoted globs are furthermore
restricted to alphanumeric characters, forward slashes, asterisks,
question marks, underscores, and periods.  When in doubt, quote.</p>
<div class="hint">
<p class="first admonition-title">Hint</p>
<p class="last">Both globs and regexes need to match the <em>entire path</em> to
requested file, relative to the main content file directory
(<tt class="docutils literal">$basedir/main</tt>); and furthermore globs and regexes have
different matching behavior, in that a regex will match as long it
matches against the beginning of the target string, but a glob
needs to match all the way to the end.  So if someone requests
<tt class="docutils literal"><span class="pre">http://bozoland.org/dingdong/frogling.mp3</span></tt>, the path against which
your pattern will be matched will be <tt class="docutils literal">dingdong/frogling.mp3</tt>,
<em>without</em> a leading forward slash.  <tt class="docutils literal">*frogling*</tt> would match it,
as would <tt class="docutils literal"><span class="pre">regex:.*frogling</span></tt>; <tt class="docutils literal">frogling.mp3</tt> wouldn't, and
neither would <tt class="docutils literal">dingdong</tt>, but <tt class="docutils literal">regex:dingdong</tt> would.</p>
</div>
<p>The date options are <tt class="docutils literal">F</tt>, <tt class="docutils literal">T</tt>, and the name-value option <tt class="docutils literal">fmt</tt>.
<tt class="docutils literal">F</tt> and <tt class="docutils literal">T</tt> are incompatible.  <tt class="docutils literal">T</tt> is the default (so its use is
actually not necessary except perhaps for readability); it means that
the condition will return true only if the current time matches
against the date range specified.</p>
<p><tt class="docutils literal">F</tt> means that the date is matched against the filename using a
regular expression derived from a format (the <tt class="docutils literal">fmt</tt> option); the
default format is <tt class="docutils literal">MMDDYYYY</tt>.  Formats may be specified with the
following symbols:</p>
<ul class="simple">
<li>MM (months)</li>
<li>DD (days)</li>
<li>YY (2-digit year)</li>
<li>YYYY (4-digit year)</li>
<li>HH (hours, 24 hour clock)</li>
<li>mm (minutes)</li>
<li>PM (AM or PM)</li>
<li>hh (hours, 12 hour clock)</li>
</ul>
<p>Any additional characters in the format become a literal part of the
regular expression.  The <tt class="docutils literal">fmt</tt> option has no meaning and may not be
used when matching against the current time.</p>
<p>If the pre and post lists are both empty, the special form <tt class="docutils literal">default</tt>
may be used.   Also, if a rule applies unconditionally, the condition
may be omitted.  Therefore, the following four forms are equivalent:</p>
<pre class="literal-block">
*: pre: [], post: []
*: default
pre: [], post: []
default
</pre>
<p>For regex rules, it is possible for the filenames in the pre and post
lists to back-reference named groups in the matching regex.  Named or
numbered group references can be used, with either a shell-like
interpolation style:</p>
<pre class="literal-block">
regex:^/shows/(?P&lt;showname&gt;[^/]+)/.*\.mp3:
   pre:  [&quot;intro/$showname.mp3&quot;, &quot;ad/${showname}.mp3&quot;]
   post: [&quot;notices/$1.mp3&quot;, &quot;outro/${1}.mp3&quot;]
</pre>
<p>or the style used by backreferences in Python <a class="reference external" href="http://www.python.org/doc/current/lib/match-objects.html">regular expression
expansions</a>:</p>
<pre class="literal-block">
regex:^/shows/(?P&lt;showname&gt;[^/]+)/.*\.mp3:
   pre:  [&quot;intro/\\g&lt;showname&gt;.mp3&quot;]
   post: [&quot;outro/\\1.mp3&quot;]
</pre>
<p>Note that these forms need to be quoted.</p>
<div class="warning">
<p class="first admonition-title">Warning</p>
<p>Back-references can be used with compound conditions only
if they refer to the last matching element in the compound
condition -- and if the last element is itself compound, the last
matching element of it, etc.  For instance, the first of the next
two rules will work, and the second will not:</p>
<pre class="literal-block">
# if this matches, the match result of the regex will be
# returned, and the back-reference will work
and(&gt;01-01-2001, (and(*nougat*, regex:&quot;(foo|bar)&quot;))):
    pre: [&quot;$1.mp3&quot;]
    post: []

# if this matches, the match result of the date match
# will be returned, and back-references don't work
# with those, so the literal string '$1.mp3' will be
# used instead -- probably not what you want
and((and(*nougat*, regex:&quot;(foo|bar)&quot;), &gt;01-01-2001)):
    pre: [&quot;$1.mp3&quot;]
    post: []
</pre>
<p class="last">With <tt class="docutils literal">and</tt>, the last matching element will always the very last
element.   With <tt class="docutils literal">or</tt>, however, that is not the case -- as soon as
one of an <tt class="docutils literal">or</tt> compound condition's sub-matchers matches, that
match is returned and subsequent sub-matchers are ignored.</p>
</div>
<p>It is convenient under some circumstances to nest lists of rules, with
a conditional qualifier shared by all of them.  To do this, enclose
the nested list of rules in matching brackets:</p>
<pre class="literal-block">
regex:shows/(?P&lt;showname&gt;[^/]+)/.*: [
    &lt;=09-01-2005 [F]: default
    09-02-2005 - 10-14-2006 [F]:
       pre: [&quot;intro/$showname.mp3&quot;]
       post: []
    &gt;10-15-2006 [F]:
       pre: [current.mp3]
       post: [current.mp3]
    ]
</pre>
<p>For a complete reference, see the <a class="reference internal" href="#appendix-i-ewaconf-formal-grammar-specification">grammar specification</a> below.</p>
</div>
</div>
<div class="section" id="checking-the-syntax-of-the-configuration-files">
<h2><a class="toc-backref" href="#id26">Checking the Syntax of the Configuration Files</a></h2>
<p>The <a class="reference internal" href="#ewabatch">ewabatch</a> script, when run with the <tt class="docutils literal"><span class="pre">-t</span></tt> option, will perform
a syntax check on both <tt class="docutils literal">ewa.conf</tt> and the rulefile, and either exit
with a <tt class="docutils literal">Syntax OK</tt> message or blow up with a possibly helpful
traceback.</p>
</div>
<div class="section" id="configuring-the-web-server">
<h2><a class="toc-backref" href="#id27">Configuring the Web Server</a></h2>
<p>Two recommended options for integrating ewa with a web server are
discussed below. <a class="footnote-reference" href="#id9" id="id4">[4]</a></p>
<div class="section" id="id5">
<h3><a class="toc-backref" href="#id28">Lighttpd</a></h3>
<p>First of all, enable <tt class="docutils literal">fastcgi</tt> in <tt class="docutils literal">ewa.conf</tt>.  If you are using
<a class="reference external" href="http://lighttpd.net/">lighttpd</a> in version 1.4.11 or lower, set <tt class="docutils literal">sendfile_header</tt> to
<tt class="docutils literal"><span class="pre">'X-LIGHTTPD-send-file'</span></tt>.</p>
<p>Then use something like the following lighttpd configuration:</p>
<pre class="literal-block">
server.modules = ( &quot;mod_access&quot;,
                   &quot;mod_fastcgi&quot;,
                   &quot;mod_accesslog&quot;,
                   &quot;mod_staticfile&quot; )

server.document-root = &quot;/path/to/basedir&quot;
server.errorlog      = &quot;/var/log/lighttpd/error.log&quot;
server.port          = 80
accesslog.filename   = &quot;/var/log/lighttpd/access.log&quot;

fastcgi.server = (
                  &quot;/&quot; =&gt;
                    ( &quot;127.0.0.1&quot; =&gt;
                      (
                        &quot;host&quot; =&gt; &quot;127.0.0.1&quot;,
                        &quot;port&quot; =&gt; 5000,
                        &quot;check-local&quot; =&gt; &quot;disable&quot;,
                        # note: this is for lighttpd &lt; 1.5.
                        # for 1.5, apparently you do instead:
                        # proxy-core.allow-x-sendfile = &quot;enable&quot;
                        &quot;allow-x-send-file&quot; =&gt; &quot;enable&quot;
                      )
                    )
                )

</pre>
</div>
<div class="section" id="apache-with-mod-xsendfile">
<h3><a class="toc-backref" href="#id29">Apache with mod_xsendfile</a></h3>
<p>TBD. This should be a fairly straightforward combination of <a class="reference external" href="http://www.mems-exchange.org/software/scgi/">mod_scgi</a> and
<a class="reference external" href="http://celebnamer.celebworld.ws/stuff/mod_xsendfile/">mod_xsendfile</a>.</p>
</div>
</div>
</div>
<div class="section" id="using-the-cli-programs">
<h1><a class="toc-backref" href="#id30">Using The CLI Programs</a></h1>
<p>Below are summaries of the commandline options of <tt class="docutils literal">ewa</tt> and
<tt class="docutils literal">ewabatch</tt>, and also for a third less important program,
<tt class="docutils literal">ewasplice</tt>, which provides lower-level access to ewa's splicing
facilities.</p>
<div class="section" id="ewabatch">
<h2><a class="toc-backref" href="#id31"><tt class="docutils literal">ewabatch</tt></a></h2>
<p>usage: <tt class="docutils literal">ewabatch</tt> [options] [files]</p>
<p>Produces a combined MP3 file according to the specified rules.</p>
<dl class="docutils">
<dt>options:</dt>
<dd><table class="first last docutils option-list" frame="void" rules="none">
<col class="option" />
<col class="description" />
<tbody valign="top">
<tr><td class="option-group">
<kbd><span class="option">-h</span>, <span class="option">--help</span></kbd></td>
<td>show this help message and exit</td></tr>
<tr><td class="option-group" colspan="2">
<kbd><span class="option">-c <var>CONFIGFILE</var></span>, <span class="option">--config=<var>CONFIGFILE</var></span></kbd></td>
</tr>
<tr><td>&nbsp;</td><td>path to ewa config file</td></tr>
<tr><td class="option-group" colspan="2">
<kbd><span class="option">-r</span>, <span class="option">--recursive</span></kbd></td>
</tr>
<tr><td>&nbsp;</td><td>recurse through directories</td></tr>
<tr><td class="option-group" colspan="2">
<kbd><span class="option">--rulefile=<var>RULEFILE</var></span></kbd></td>
</tr>
<tr><td>&nbsp;</td><td>specify a rulefile</td></tr>
<tr><td class="option-group">
<kbd><span class="option">-d</span>, <span class="option">--debug</span></kbd></td>
<td>print debugging information</td></tr>
<tr><td class="option-group">
<kbd><span class="option">-n</span>, <span class="option">--dry-run</span></kbd></td>
<td>don't do anything, just print what would be done</td></tr>
<tr><td class="option-group" colspan="2">
<kbd><span class="option">-e <var>ENGINE</var></span>, <span class="option">--engine=<var>ENGINE</var></span></kbd></td>
</tr>
<tr><td>&nbsp;</td><td>which splicing engine to use (default ewa splicer,
mp3cat, or sox)</td></tr>
<tr><td class="option-group">
<kbd><span class="option">-a</span>, <span class="option">--absolute</span></kbd></td>
<td>interpret file paths relative to the filesystem rather
than the basedir (default: no)</td></tr>
<tr><td class="option-group" colspan="2">
<kbd><span class="option">-t</span>, <span class="option">--configtest</span></kbd></td>
</tr>
<tr><td>&nbsp;</td><td>just test the config file for syntax errors</td></tr>
<tr><td class="option-group">
<kbd><span class="option">-x</span>, <span class="option">--max-age</span></kbd></td>
<td>in recursive mode, to force regeneration of all files,
pass <tt class="docutils literal"><span class="pre">-1</span></tt>.  To regenerate only files that have changed,
pass <tt class="docutils literal">0</tt>.  If you pass a higher number <tt class="docutils literal">N</tt>, any file
older than <tt class="docutils literal">N</tt> minutes will be regenerated</td></tr>
<tr><td class="option-group">
<kbd><span class="option">-D</span>, <span class="option">--delete</span></kbd></td>
<td>delete files in combined directory that aren't
in the main directory</td></tr>
<tr><td class="option-group">
<kbd><span class="option">-V</span>, <span class="option">--no-vbr</span></kbd></td>
<td>don't put vbr files in the combined directory</td></tr>
<tr><td class="option-group" colspan="2">
<kbd><span class="option">-B</span>, <span class="option">--no-broken</span></kbd></td>
</tr>
<tr><td>&nbsp;</td><td>don't put broken files in the combined directory</td></tr>
<tr><td class="option-group">
<kbd><span class="option">-s</span>, <span class="option">--sleep</span></kbd></td>
<td>number of seconds to sleep between file generations;
default: 0.0</td></tr>
</tbody>
</table>
</dd>
</dl>
<div class="hint">
<p class="first admonition-title">Hint</p>
<p class="last">With both <tt class="docutils literal">ewabatch</tt> and <tt class="docutils literal">ewa</tt>, if you don't specify a config
file, ewa will look for it in <tt class="docutils literal"><span class="pre">~/.ewa/ewa.conf</span></tt> and
<tt class="docutils literal">/etc/ewa.conf</tt>.</p>
</div>
</div>
<div class="section" id="ewa">
<h2><a class="toc-backref" href="#id32"><tt class="docutils literal">ewa</tt></a></h2>
<p>usage: <tt class="docutils literal">ewa</tt> [options]</p>
<p>Starts ewa's WSGI application that produces combined MP3 files
according to the specified rules.</p>
<dl class="docutils">
<dt>options:</dt>
<dd><table class="first last docutils option-list" frame="void" rules="none">
<col class="option" />
<col class="description" />
<tbody valign="top">
<tr><td class="option-group">
<kbd><span class="option">-h</span>, <span class="option">--help</span></kbd></td>
<td>show this help message and exit</td></tr>
<tr><td class="option-group" colspan="2">
<kbd><span class="option">-c <var>CONFIGFILE</var></span>, <span class="option">--config=<var>CONFIGFILE</var></span></kbd></td>
</tr>
<tr><td>&nbsp;</td><td>path to ewa config file</td></tr>
<tr><td class="option-group" colspan="2">
<kbd><span class="option">-D</span>, <span class="option">--nodaemonize</span></kbd></td>
</tr>
<tr><td>&nbsp;</td><td>don't daemonize, regardless of config settings</td></tr>
<tr><td class="option-group" colspan="2">
<kbd><span class="option">--lighttpd-hack</span></kbd></td>
</tr>
<tr><td>&nbsp;</td><td>force SCRIPT_NAME to be &quot;&quot;, regardless of what
was sent by the web server. (Needed for some
versions of lighttpd under some circumstances.)</td></tr>
</tbody>
</table>
</dd>
</dl>
</div>
<div class="section" id="ewasplice">
<h2><a class="toc-backref" href="#id33"><tt class="docutils literal">ewasplice</tt></a></h2>
<p>usage: <tt class="docutils literal">ewasplice</tt> [options] files</p>
<p>This utility splices MP3 files together using the ewa splicer, but
doesn't use the managed directories or perform automatic
transcoding. You have to specify a file as  &quot;tagfile&quot; so it knows
where to get id3 tags.</p>
<dl class="docutils">
<dt>options:</dt>
<dd><table class="first last docutils option-list" frame="void" rules="none">
<col class="option" />
<col class="description" />
<tbody valign="top">
<tr><td class="option-group">
<kbd><span class="option">-h</span>, <span class="option">--help</span></kbd></td>
<td>show this help message and exit</td></tr>
<tr><td class="option-group" colspan="2">
<kbd><span class="option">-o <var>OUT</var></span>, <span class="option">--output=<var>OUT</var></span></kbd></td>
</tr>
<tr><td>&nbsp;</td><td>output file (default: stdout)</td></tr>
<tr><td class="option-group" colspan="2">
<kbd><span class="option">-t <var>TAGFILE</var></span>, <span class="option">--tagfile=<var>TAGFILE</var></span></kbd></td>
</tr>
<tr><td>&nbsp;</td><td>tag file</td></tr>
<tr><td class="option-group">
<kbd><span class="option">-d</span>, <span class="option">--debug</span></kbd></td>
<td>print debugging information</td></tr>
<tr><td class="option-group" colspan="2">
<kbd><span class="option">-s</span>, <span class="option">--sanitycheck</span></kbd></td>
</tr>
<tr><td>&nbsp;</td><td>sanity check the input mp3 files</td></tr>
<tr><td class="option-group" colspan="2">
<kbd><span class="option">-e <var>ENGINE</var></span>, <span class="option">--engine=<var>ENGINE</var></span></kbd></td>
</tr>
<tr><td>&nbsp;</td><td>which splicing engine to use (default ewa splicer,
mp3cat, or sox)</td></tr>
</tbody>
</table>
</dd>
</dl>
</div>
</div>
<div class="section" id="appendix-i-ewaconf-formal-grammar-specification">
<h1><a class="toc-backref" href="#id34">Appendix I. <tt class="docutils literal">ewaconf</tt> Formal Grammar Specification</a></h1>
<div class="section" id="normative-ebnf">
<h2><a class="toc-backref" href="#id35">Normative EBNF</a></h2>
<p>The below is an EBNF grammar for the rule configuration format:</p>
<pre class="literal-block">
grammar        := cond_rule [','? cond_rule]*
rulelist       := '[' cond_rule [','? cond_rule]* ']'
cond_rule      := [cond ':']? rule
rule           := simplerule | rulelist
simplerule     := prelist ','? postlist | postlist ','? prelist | 'default'
prelist        := 'pre' ':' speclist
postlist       := 'post' ':' speclist
speclist       := '[' [specifier [',' specifier]*]? ']'
specifier      := string
string         := BAREWORD | QWORD
cond           := cond_expr | simple_cond
cond_expr      := cond_op '(' cond [',' cond]+ ')'
cond_expr      := NOT '(' cond ')'
cond_op        := 'and' | 'or'
simple_cond    := regex | glob | datespec
regex          := BAREREGEX condopts? | QREGEX condopts?
glob           := string condopts?
datespec       := daterange condopts?
daterange      := [date '-' date] | [ datecompare date ] | date
datecompare    := '&lt;' | '&lt;=' | '&gt;' | '&gt;=' | '='
date           := DATE | DATETIME
condopts       := '[' condopt [',' condopt]* ']'
condopt        := BAREWORD | BAREWORD '=' BAREWORD
</pre>
</div>
<div class="section" id="lexical-details">
<h2><a class="toc-backref" href="#id36">Lexical Details</a></h2>
<div class="section" id="significant-tokens">
<h3><a class="toc-backref" href="#id37">Significant Tokens</a></h3>
<p>The tokens that the lexer must produce will be:</p>
<blockquote>
<dl class="docutils">
<dt>BAREWORD</dt>
<dd>an unquoted string with alphanumeric characters, asterisks,
backslashes, question marks, underscores, or periods.</dd>
<dt>QWORD</dt>
<dd>a string delimited by single or double quotation marks.  Internal
quotation marks of the same type used as the delimiter must be
escaped.</dd>
<dt>BAREREGEX</dt>
<dd>a string that matches a regex; should start with <tt class="docutils literal">regex:</tt>,
followed by an unquoted string with the same restrictions as
BAREWORD above.</dd>
<dt>QREGEX</dt>
<dd>like a BAREREGEX, but the regex, after the <tt class="docutils literal">regex:</tt> prefix,
is delimited by single or double quotation marks, and escaping
(except of quotation marks) is not necessary.</dd>
<dt>DATE</dt>
<dd>MM-DD-YYYY format.  The separator can also be a slash (/) or a
period (.), but the same separator must be used in both
positions.</dd>
<dt>DATETIME</dt>
<dd>MM-DD-YYYY HHMM format.  The separator can also be a slash or
period, as with DATE, and the space before the hour can be either
a space or the previously used separator.</dd>
<dt>DEFAULT</dt>
<dd>'default'</dd>
<dt>PRE</dt>
<dd>'pre'</dd>
<dt>POST</dt>
<dd>'post'</dd>
<dt>AND</dt>
<dd>'and'</dd>
<dt>OR</dt>
<dd>'or'</dd>
<dt>OP</dt>
<dd>'&lt;', '&lt;=', '&gt;', '&gt;=', '='</dd>
<dt>DASH</dt>
<dd>'-'</dd>
<dt>COMMA</dt>
<dd>','</dd>
<dt>COLON</dt>
<dd>':'</dd>
<dt>LBRACK</dt>
<dd>'['</dd>
<dt>RBRACK</dt>
<dd>']'</dd>
<dt>LPAREN</dt>
<dd>'('</dd>
<dt>RPAREN</dt>
<dd>')'</dd>
</dl>
</blockquote>
</div>
<div class="section" id="ignored-tokens">
<h3><a class="toc-backref" href="#id38">Ignored Tokens</a></h3>
<p>Any text on a line after a pound sign (#) is a comment and is ignored.
Whitespace, including line returns, is ignored between tokens.
Indentation may be freely used to clarify patterns.</p>
</div>
</div>
<div class="section" id="complete-example">
<h2><a class="toc-backref" href="#id39">Complete Example</a></h2>
<pre class="literal-block">
# test rule file.

# comments and blank lines are ignored.
08/01/2005-12/01/2006: default

&gt;08/08/2006: pre: [lumpy.mp3], post: []

shows/bl/*: 
  pre: [intro/bl.mp3, ad/generic.mp3]
  post: [outro/bl.mp3]

regex:&quot;^/shows/(?P&lt;nick&gt;[a-z][a-z0-9]+)/(?P=nick).*\.mp3&quot; [I]: 
  pre: [intro/newyear.mp3], post: []

=01/20/2001 [F, fmt=MMDDYYYY]: [
   shows/studio/*: 
      pre: []
      post: [outro/studio.mp3]
   shows/pingpong/*:
      pre: [foomanchu.mp3,bingo.mp3]
      post: []
   pre: [plop.mp3], post: []
   ]
default
</pre>
<table class="docutils footnote" frame="void" id="id6" rules="none">
<colgroup><col class="label" /><col /></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#id1">[1]</a></td><td>There are use cases in which you might want more than one
content file -- one for each segment of a radio program, for
instance -- but this usage is not currently supported.</td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="id7" rules="none">
<colgroup><col class="label" /><col /></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#id2">[2]</a></td><td>The stated default value of this config variable, and of the
several following which refer to the configuration of the <a class="reference external" href="http://fastcgi.com/">FCGI</a> and
<a class="reference external" href="http://www.mems-exchange.org/software/scgi/">SCGI</a> daemons,  are actually enforced by <a class="reference external" href="http://cheeseshop.python.org/pypi/flup">flup</a>; the value help in
<tt class="docutils literal">Config</tt>  object for all of them is actually <tt class="docutils literal">None</tt>.</td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="id8" rules="none">
<colgroup><col class="label" /><col /></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#id3">[3]</a></td><td>Actually, there is a third format -- a special dialect of <a class="reference external" href="http://www.json.org/">JSON</a>
-- but it isn't very useful and may be dropped in a future
release.</td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="id9" rules="none">
<colgroup><col class="label" /><col /></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#id4">[4]</a></td><td>Other options are possible.  In addition to nginx, mentioned
elsewhere, it would be possible run ewa's WSGI application in
another WSGI container or even a CGI.  With Apache's
<tt class="docutils literal">mod_rewrite</tt> it is possible to detect whether a static file is
available and serve it directly if so, and only call a splicing
backend if not, which, if X-Sendfile were not available, could
accomplish much the same thing with an external redirect.</td></tr>
</tbody>
</table>
</div>
</div>
</div>
<div class="footer">
<hr class="footer" />
<a class="reference external" href="ewamanual.rst">View document source</a>.

</div>
</body>
</html>
